package com.syh.jn.scm.infrastructure.repository.impl.supplier.purchase;

import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.fastjson.JSONObject;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoMybatisImplTmpl;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseOrderReadRepository;
import com.syh.jn.scm.dto.supplier.purchase.PurStatisticalAmountVo;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseOrderItemVo;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseOrderVo;
import com.syh.jn.scm.infrastructure.repository.model.purchase.PurchaseOrderItemModel;
import com.syh.jn.scm.infrastructure.repository.model.purchase.PurchaseOrderModel;
import com.syh.jn.scm.infrastructure.repository.utils.MybatisTemplate;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import lombok.extern.java.Log;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 采购订单查询
 */
@Log
@Repository("purchaseOrderReadRepositoryMbImpl")
public class PurchaseOrderReadRepositoryMbImpl implements PurchaseOrderReadRepository {
  private AggregateRepoMybatisImplTmpl<PurchaseOrderVo, PurchaseOrderModel, Long> orderImpl =
            new AggregateRepoMybatisImplTmpl.Builder().listTypeClass(PurchaseOrderVo.class).modelClass(PurchaseOrderModel.class).build();
  private AggregateRepoMybatisImplTmpl<PurchaseOrderItemVo, PurchaseOrderItemVo, Long> itemImpl =
          new AggregateRepoMybatisImplTmpl.Builder().listTypeClass(PurchaseOrderItemVo.class).modelClass(PurchaseOrderItemModel.class).build();
  @Override
  public boolean purItemExistsById(String column, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq(column,id));
    return orderImpl.getCount(wrapper) > 0;
  }

  @Override
  public List<PurchaseOrderItemVo> getItemsByPurchaseOrderId(Long purchaseOrderId) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq("purchaseOrderId",purchaseOrderId));
    return this.itemImpl.getList(wrapper);
  }

  @Override
  public PurchaseOrderItemVo getItemByItemId(Long orderItemId) {
    return this.itemImpl.getById(orderItemId);
  }

  @Override
  public PurchaseOrderItemVo getByGoodsId(Long goodsId, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq("goodsId",goodsId)).append(Restrictions.eq("id",id));
    return this.itemImpl.getOne(wrapper);
  }

  @Override
  public List<PurchaseOrderItemVo> getItemsByPurchaseOrderIds(Long[] purchaseOrderIds) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.in("purchaseOrderId",purchaseOrderIds));
    return this.itemImpl.getList(wrapper);
  }

  @Override
  public PurStatisticalAmountVo statisticalAmount(Wrapper wrapper) {
    SQL sql = new SQL() {{
      SELECT("SUM(pur.TOTAL_AMOUNT) AS statisticalTotalAmount",
              "SUM(pur.TOTAL_IN_AMOUNT) AS statisticalTotalInAmount");
      FROM("T_PUR_PURCHASE_ORDER pur");
    }};
    StringBuffer sqlString = new StringBuffer(sql.toString());
    BaseResolve resolveToSQL = new ResolveToSQL(wrapper,this.orderImpl.getWrapperParseMethods());
    sqlString.append(" WHERE 1 = 1").append(resolveToSQL.resolve());
    Map<String, Object> list = MybatisTemplate.selectOne(sqlString.toString());
    PurStatisticalAmountVo purStatisticalAmountVo = JSONObject.parseObject(JSONObject.toJSONString(list), PurStatisticalAmountVo.class);
    return purStatisticalAmountVo;
  }

  @Override
  public PurStatisticalAmountVo statisticalAmountByOrder(Wrapper we) {

    StringBuffer sqlString = new StringBuffer("SELECT ");
    sqlString.append("SUM(pur.totalAmount) AS statisticalTotalAmount, ");
    sqlString.append("SUM(pur.totalInAmount) AS statisticalTotalInAmount ");
    sqlString.append("FROM ( ");

    StringBuffer subString = new StringBuffer(this.orderImpl.getQuerySql().toString());
    BaseResolve resolveToSQL;
    if (this.orderImpl.getWrapperParseMethods() == null) {
      resolveToSQL = new ResolveToSQL(we);
    } else {
      resolveToSQL = new ResolveToSQL(we, this.orderImpl.getWrapperParseMethods());
    }
    subString.append(" WHERE 1=1 ");
    subString.append(resolveToSQL.resolve());
    sqlString.append(subString).append(" ) pur");

    Map<String, Object> map = MybatisTemplate.selectOne(sqlString.toString());
    PurStatisticalAmountVo vo = JSONObject.parseObject(JSONObject.toJSONString(map),PurStatisticalAmountVo.class);
    return vo;
  }

  @Override
  public PurchaseOrderVo getById(Long id) {
    PurchaseOrderVo purchaseOrderVo = this.orderImpl.getById(id);
    if (purchaseOrderVo == null) {
      return purchaseOrderVo;
    }
    purchaseOrderVo.setItems(this.getItemsByPurchaseOrderId(purchaseOrderVo.getId()));
    return purchaseOrderVo;
  }

  @Override
  public PurchaseOrderVo getOne(Wrapper wrapper) {
    PurchaseOrderVo purchaseOrderVo = this.orderImpl.getOne(wrapper);
    if (purchaseOrderVo == null) {
      return purchaseOrderVo;
    }
    purchaseOrderVo.setItems(this.getItemsByPurchaseOrderId(purchaseOrderVo.getId()));
    return purchaseOrderVo;
  }

  @Override
  public boolean contains(Long id) {
    return this.orderImpl.contains(id);
  }

  @Override
  public List<PurchaseOrderVo> getList(Wrapper wrapper) {
    return this.orderImpl.getList(wrapper);
  }

  @Override
  public List<PurchaseOrderVo> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return this.orderImpl.findListPage(wrapper,startRow,count);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    StringBuffer sqlSb = new StringBuffer();
    String viewSql = this.orderImpl.getQuerySql().toString();
    String viewSqlAry[] = viewSql.split("\\s*FROM\\s*");
    sqlSb.append("SELECT COUNT(DISTINCT pur.ID) AS COUNT FROM ");
    for (int i = 1; i <= viewSqlAry.length - 1; i++) {
      if (i > 1) {
        sqlSb.append(" FROM ").append(viewSqlAry[i]);
      } else {
        sqlSb.append(viewSqlAry[i]);
      }
    }
    BaseResolve resolveToSQL = new ResolveToSQL(wrapper, this.orderImpl.getWrapperParseMethods());
    sqlSb.append(" WHERE 1=1 ");
    sqlSb.append(resolveToSQL.resolve());

    Map resultM = MybatisTemplate.selectOne(sqlSb.toString());
    return Integer.parseInt(resultM.get("COUNT").toString());
  }

  public PurchaseOrderReadRepositoryMbImpl() {
    SQL purchaseOrderSql = new SQL(){{
            SELECT(
              "DISTINCT NULL",
              SQLAliasGenerateUtil.aliasGenerate(PurchaseOrderModel.class, "pur", null),
              "upStream.NAME AS upStreamCompanyName",
              "sales.CODE AS salesOrderCode"
      );
      FROM("T_PUR_PURCHASE_ORDER pur");
      LEFT_OUTER_JOIN("T_BASE_UPSTREAM upStream on upStream.ID = pur.UP_STREAM_COMPANY_ID");
      LEFT_OUTER_JOIN("T_SALE_ORDER sales on pur.SALES_ORDER_ID = sales.ID");
      LEFT_OUTER_JOIN("T_PUR_PURCHASE_ORDER_ITEM item ON item.PURCHASE_ORDER_ID = pur.ID");
    }};
    this.orderImpl.setQuerySql(purchaseOrderSql);
    //初始化查询条件 purchasOrderMap
    Map<String, String> purchaseOrderMap = new HashMap<>();
    purchaseOrderMap.put("id", "pur.ID");
    purchaseOrderMap.put("code", "pur.CODE");
    purchaseOrderMap.put("extCode", "pur.EXT_CODE");
    purchaseOrderMap.put("deliName", "pur.DELI_NAME");
    purchaseOrderMap.put("name", "upStream.NAME");
    purchaseOrderMap.put("deliTel", "pur.DELI_TEL");
    purchaseOrderMap.put("ordState", "pur.ORD_STATE");
    purchaseOrderMap.put("deliveryState", "pur.DELIVERY_STATE");
    purchaseOrderMap.put("collectState", "pur.COLLECT_STATE");
    purchaseOrderMap.put("logisticsCompanyId", "pur.LOGISTICS_COMPANY_ID");
    purchaseOrderMap.put("statementId", "pur.STATEMENT_ID");
    purchaseOrderMap.put("remark", "pur.REMARK");
    purchaseOrderMap.put("businessEntityId", "pur.BUSINESS_ENTITY_ID");
    purchaseOrderMap.put("inputDateTimestamp", "pur.INPUT_DATE_TIMESTAMP");
    purchaseOrderMap.put("orderType", "pur.ORDER_TYPE");
    purchaseOrderMap.put("createTimeStamp", "pur.CREATE_TIME_STAMP");
    purchaseOrderMap.put("saleCode", "sales.CODE");
    purchaseOrderMap.put("salesOrderId", "sales.SALES_ORDER_ID");
    purchaseOrderMap.put("goodsId", "item.GOODS_ID");
    purchaseOrderMap.put("goodsName", "item.GOODS_NAME");
    this.orderImpl.setWrapperParseMethods(propertyName -> {
      return purchaseOrderMap.get(propertyName);
    });

    SQL purchaseOrderItemSql = new SQL(){{
      SELECT(
              SQLAliasGenerateUtil.aliasGenerate(PurchaseOrderItemModel.class, "item", null)
      );
      FROM("T_PUR_PURCHASE_ORDER_ITEM item");
      LEFT_OUTER_JOIN("T_PUR_PURCHASE_ORDER pur ON item.PURCHASE_ORDER_ID = pur.ID");
    }};
    this.itemImpl.setQuerySql(purchaseOrderItemSql);
    //初始化查询条件 purchasOrderItemMap
    Map<String, String> purchasOrderItemMap = new HashMap<>();
    purchasOrderItemMap.put("id", "item.ID");
    purchasOrderItemMap.put("code", "pur.CODE");
    purchasOrderItemMap.put("ordState", "pur.ORD_STATE");
    purchasOrderItemMap.put("deliveryState", "pur.DELIVERY_STATE");
    purchasOrderItemMap.put("collectState", "pur.COLLECT_STATE");
    purchasOrderItemMap.put("statementId", "pur.STATEMENT_ID");
    purchasOrderItemMap.put("businessEntityId", "pur.BUSINESS_ENTITY_ID");
    purchasOrderItemMap.put("inputDateTimestamp", "pur.INPUT_DATE_TIMESTAMP");
    purchasOrderItemMap.put("orderType", "pur.ORDER_TYPE");
    purchasOrderItemMap.put("goodsId", "item.GOODS_ID");
    purchasOrderItemMap.put("goodsName", "item.GOODS_NAME");
    purchasOrderItemMap.put("purchaseOrderId", "item.PURCHASE_ORDER_ID");
    this.itemImpl.setWrapperParseMethods(propertyName -> {
      return purchasOrderItemMap.get(propertyName);
    });

  }
}
